package com.wechat.controller;

import com.wechat.entity.User;
import com.wechat.entity.config.wft.SwiftpassConfig;
import com.wechat.service.UserService;
import com.wechat.utils.ActionResult;
import com.wechat.utils.MD5;
import com.wechat.utils.SignUtils;
import com.wechat.utils.XmlUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

/**
 * @Description 威富通微信支付
 * @Author J
 * @Date 2018/5/30 9:57
 **/
@RestController
@RequestMapping("/api/v1")
public class WftWxPayController {


    private static Logger log = LoggerFactory.getLogger(WftWxPayController.class);


    private final static String version = "2.0";
    private final static String charset = "UTF-8";
    private final static String sign_type = "MD5";

    @Value("${wechat.miniapp.appid}")
    private String appId;


    @Autowired
    private UserService userService;

    /**
     * 支付请求
     *
     * @throws ServletException
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    @PostMapping("/pay/wft_wx")
    public ActionResult pay(String key, HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("支付请求...");

        ActionResult actionResult = new ActionResult();

        User user = userService.getLoginUser(key);
        if (user == null) {
            actionResult.setLoginTimeout(true);
            actionResult.setMessage("用户登录超时");
            return actionResult;
        }

        user = userService.findById(user.getId());

        SortedMap<String, String> map = XmlUtils.getParameterMap(request);

        map.put("service", "pay.weixin.jspay");
        map.put("version", version);
        map.put("charset", charset);
        map.put("sign_type", sign_type);
        map.put("mch_id", SwiftpassConfig.mch_id);
        map.put("is_raw", "1");
        //1表示小程序支付
        map.put("is_minipg", "1");
        //充值订单号
        map.put("out_trade_no", "test" + System.currentTimeMillis());
        map.put("body", "测试的商品名");
        //微信用户关注商家公众号的openid
        map.put("sub_openid", user.getOpenId());
        //appId  小程序id
        map.put("sub_appid", appId);
        //回调能够传递的参数
        map.put("attach", "test attach");
        //金额 以分为单位
        map.put("total_fee", "1");
        //订单创建ip
        map.put("mch_create_ip", getIpAddr(request));
        //回调地址
        map.put("notify_url", SwiftpassConfig.notify_url);
        //随机字符串
        map.put("nonce_str", String.valueOf(System.currentTimeMillis()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + SwiftpassConfig.key, "utf-8");
        map.put("sign", sign);

        String reqUrl = SwiftpassConfig.req_url;
        log.debug("reqUrl：" + reqUrl);

        log.debug("reqParams:" + XmlUtils.parseXML(map));
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        Map<String, String> resultMap = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                res = XmlUtils.toXml(resultMap);
                log.debug("请求结果：" + res);
                if (!SignUtils.checkParam(resultMap, SwiftpassConfig.key)) {
                    res = "验证签名不通过";
                } else {
                    if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                        String pay_info = resultMap.get("pay_info");
                        log.debug("pay_info : " + pay_info);
                        res = "ok";
                        actionResult.setSuccess(true);
                        actionResult.setMessage("测试成功");
                    }
                }
            } else {
                res = "操作失败";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "系统异常";
        } finally {

            if (response != null) {
                response.close();
            }

            if (client != null) {
                client.close();
            }
        }

        if (!"ok".equals(res)) {
            resultMap.put("status", "500");
            resultMap.put("msg", res);
        }
        actionResult.put("data", resultMap);

        return actionResult;
    }

    /**
     * 回调
     */
    @PostMapping("/pay/wft_wx/notify")
    public String notify(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        log.debug("收到通知...回调开始了");
        req.setCharacterEncoding("utf-8");

        String respString = "error";
        try {
            String resString = XmlUtils.parseRequst(req);
            log.debug("请求的内容：" + resString);

            if (resString != null && !"".equals(resString)) {
                Map<String, String> map = XmlUtils.toMap(resString.getBytes(), "utf-8");
                String res = XmlUtils.toXml(map);
                log.debug("请求结果：" + res);
                if (map.containsKey("sign")) {
                    if (!SignUtils.checkParam(map, SwiftpassConfig.key)) {
                        log.debug("验证签名不通过");
                        respString = "error";
                    } else {
                        log.debug("验证签名通过");
                        String status = map.get("status");
                        log.debug("status is " + status);
                        if (status != null && "0".equals(status)) {
                            String result_code = map.get("result_code");
                            log.debug("result_code is " + result_code);
                            if (result_code != null && "0".equals(result_code)) {
                                log.debug("回调成功啦......");
                                log.debug("回调成功啦......");
                                log.debug("回调成功啦......");
                                log.debug("回调成功啦......");
                                log.debug("回调成功啦......");
                                respString = "success";
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
        }

        return respString;
    }


    @PostMapping("/pay/wft_wx/query")
    public ActionResult query(String rechargeId, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("订单查询...");

        ActionResult actionResult = new ActionResult();
        actionResult.setSuccess(false);

        SortedMap<String, String> map = XmlUtils.getParameterMap(req);

        map.put("service", "unified.trade.query");
        map.put("version", version);
        map.put("charset", charset);
        map.put("sign_type", sign_type);
        map.put("mch_id", SwiftpassConfig.mch_id);
        map.put("out_trade_no", rechargeId);

        String key = SwiftpassConfig.key;
        String reqUrl = SwiftpassConfig.req_url;
        map.put("nonce_str", String.valueOf(System.currentTimeMillis()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign = MD5.sign(preStr, "&key=" + key, "utf-8");
        map.put("sign", sign);

        log.debug("reqUrl:" + reqUrl);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);

            if (response != null && response.getEntity() != null) {
                Map<String, String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                res = XmlUtils.toXml(resultMap);
                log.debug("请求结果：" + res);

                if (!SignUtils.checkParam(resultMap, key)) {
                    res = "验证签名不通过";
                } else {
                    if ("0".equals(resultMap.get("status"))) {
                        if ("0".equals(resultMap.get("result_code"))) {
                            log.debug("业务成功，在这里做相应的逻辑处理");
                            String trade_state = resultMap.get("trade_state");
                            log.debug("trade_state : " + trade_state);
                            log.debug("这里商户需要同步自己的订单状态。。。");
                            actionResult.setSuccess(true);
                        } else {
                            log.debug("业务失败，尝试重新请求，并查看错误代码描叙");
                        }
                    } else {
                        log.debug("这里是请求参数有问题...");
                    }
                }
            } else {
                res = "操作失败!";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "操作失败";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if (res.startsWith("<")) {
            result.put("status", "200");
            result.put("msg", "操作成功，请在日志文件中查看");
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }

        actionResult.put("data", result);
        actionResult.setMessage("测试成功");

        return actionResult;
    }


    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        } else {
            ip = request.getHeader("X-Forwarded-For");
            if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
                int index = ip.indexOf(44);
                return index != -1 ? ip.substring(0, index) : ip;
            } else {
                return request.getRemoteAddr();
            }
        }
    }
}
